/**
 * 
 */
package com.gragra.frameStatistics;
import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntSet;
import com.gragra.data.Corpus;
import com.gragra.sampling.sequentialStructure.WordAndTagHolder;
/**
 * this is an extension of the StatisticsGenerator that also counts co-occurrences between words, it counts these
 * for words that have been used as co-occurrence words for frames.
 * @author Christoph Teichmann
 * 26.04.2013
 */
public class CoOccurrenceStatistics extends StatisticsGenerator
{
	/**
	 * returns all the words that have followed the given one, returns null, if the word was never seen
	 * @param word
	 * @return
	 */
	public IntSet getFollowers(int word)
	{
		Int2DoubleOpenHashMap m = this.forwardCounts.get(word);
		if(m == null)
		{return null;}
		return m.keySet();
	}
	/**
	 * returns all the words that have Preceded the given one, returns null, if the word was never seen
	 * @param word
	 * @return
	 */
	public IntSet getPrecedents(int word)
	{
		Int2DoubleOpenHashMap m = this.backwardCounts.get(word);
		if(m == null)
		{return null;}
		return m.keySet();
	}
	/**
	 * can be called to find out how often word was counted with otherword following it
	 * @param word
	 * @param otherword
	 * @return
	 */
	public double getForwardCoCount(int word, int otherword)
	{
		Int2DoubleOpenHashMap m = this.forwardCounts.get(word);
		if(m == null)
		{return 0.0;}
		return m.get(otherword);
	}
	/**
	 * can be called to find out how often word was counted with otherword preceding it
	 * @param word
	 * @param otherword
	 * @return
	 */
	public double getBackwardCoCount(int word, int otherword)
	{
		Int2DoubleOpenHashMap m = this.backwardCounts.get(word);
		if(m == null)
		{return 0.0;}
		return m.get(otherword);
	}
	/* (non-Javadoc)
	 * @see com.gragra.frameStatistics.StatisticsGenerator#postWordStats(int, int)
	 */
	@Override
	protected void postWordStats(int word, int integer)
	{this.putIntoMap(word,integer, this.forwardCounts);}
	/**
	 * used to add one to a co-occurrence, by handling the nested maps
	 * @param word the key for the first map
	 * @param integer the key for the nested map
	 * @param forwardCounts2 the map into which an entry is to be made
	 */
	private void putIntoMap(int word, int coOc,
			Int2ObjectOpenHashMap<Int2DoubleOpenHashMap> map)
	{
		Int2DoubleOpenHashMap inter = map.get(word);
		if(inter == null)
		{
			inter = new Int2DoubleOpenHashMap();
			map.put(word, inter);
		}
		inter.addTo(coOc, 1.0);
	}
	/* (non-Javadoc)
	 * @see com.gragra.frameStatistics.StatisticsGenerator#preWordStats(int, java.lang.Integer)
	 */
	@Override
	protected void preWordStats(int word, Integer integer)
	{this.putIntoMap(word,integer, this.backwardCounts);}
	/* (non-Javadoc)
	 * @see com.gragra.frameStatistics.StatisticsGenerator#additionalContstruction()
	 */
	@Override
	protected void additionalContstruction()
	{
		this.backwardCounts = new Int2ObjectOpenHashMap<Int2DoubleOpenHashMap>();
		this.forwardCounts = new Int2ObjectOpenHashMap<Int2DoubleOpenHashMap>();
	}
	/**
	 * the counts of co-occurrences of the form word - co-occurrence
	 */
	private Int2ObjectOpenHashMap<Int2DoubleOpenHashMap> forwardCounts;

	/**
	 * the counts of co-occurrences of the form co-occurrence - word
	 */
	private Int2ObjectOpenHashMap<Int2DoubleOpenHashMap> backwardCounts;
	/**
	 * constructs a new instance in which the use of tags can be activated with the given boolean
	 * @param c
	 * @param frameSize
	 * @param usePreMarker
	 * @param usePostMarker
	 * @param useTags
	 */
	public CoOccurrenceStatistics(Corpus<WordAndTagHolder> c, int frameSize,
			int usePreMarker, int usePostMarker, boolean useTags)
	{super(c, frameSize, usePreMarker, usePostMarker, useTags);}
	/**
	 * can be used to create an instance that will not use tags
	 * @param c
	 * @param frameSize
	 * @param usePreMarker
	 * @param usePostMarker
	 */
	public CoOccurrenceStatistics(Corpus<WordAndTagHolder> c, int frameSize,
			int usePreMarker, int usePostMarker)
	{super(c, frameSize, usePreMarker, usePostMarker);}
}